
package net.pinnoocle.playcommon.exception;

import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.pinnoocle.playcommon.response.BaseResult;
import net.pinnoocle.playcommon.response.ErrorCode;
import org.slf4j.MDC;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;


/**
 * 异常处理器
 *
 * @author ye
 * @Description
 * @create 2021-09-01 16:19
 */
@RestControllerAdvice
@Slf4j
@AllArgsConstructor
public class ShopExceptionHandler {

    /**
     * 处理自定义异常
     */
    @ExceptionHandler(ShopException.class)
    public BaseResult handleCrmException(ShopException ex) {
        BaseResult result = new BaseResult();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
            .getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            MDC.put("trace.id", request.getHeader("requestId"));
            log.error("ShopException shopException ："
                    + "请求接口 URL : [{}]"
                    + "IP : [{}]"
                    + "错误编码 : [{}]"
                    + "错误内容 : [{}]"
                , request.getRequestURL().toString(), request.getRemoteAddr(), ex.getCode(),
                ex.getMsg());
        }
        MDC.remove("trace.id");
        result.error(ex.getCode(), ex.getMsg());
        return result;
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public BaseResult handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
        BaseResult result = new BaseResult();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
            .getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            log.error("ShopExceptionHandler exception 参数有误："
                    + "请求接口 URL : [{}]"
                    + "IP : [{}]"
                    + "错误编码 : [{}]"
                    + "错误内容 : [{}]"
                , request.getRequestURL().toString(), request.getRemoteAddr(),
                +ErrorCode.WRONG_PARAMETER, ex.getMessage());
        }
        result.error(ErrorCode.WRONG_PARAMETER,
            "参数有误" + ex.getBindingResult().getFieldError().getDefaultMessage());
        return result;
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    public BaseResult handleHttpMessageNotReadableException(HttpMessageNotReadableException ex) {
        BaseResult result = new BaseResult();
        result.error(ErrorCode.JSON_FORMAT_ERROR, "JSON格式错误" + ex.getMessage());
        return result;
    }

    @ExceptionHandler(Exception.class)
    public BaseResult handleException(Exception ex) {
        log.error(ex.getMessage(), ex);
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();

            log.error("CrmExceptionHandler exception 处理总异常 :"
                            + "请求接口 URL : [{}]"
                            + "IP : [{}]"
                            + "错误编码 : [{}]"
                            + "错误内容 : [{}]"
                    , request.getRequestURL().toString(), request.getRemoteAddr(), 9999,
                    ex.getMessage());
            if (log.isTraceEnabled()) {
                Enumeration<String> enu = request.getParameterNames();
                while (enu.hasMoreElements()) {
                    String paraName = enu.nextElement();
                    log.trace("\n " + paraName + ": " + request.getParameter(paraName));
                }
            }

        }
        return new BaseResult().error(JSON.toJSONString(ex));
    }
}
